import 'dart:convert';
import 'dart:math';
import 'package:dio/dio.dart';
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:uuid/uuid.dart';
import 'package:crypto/crypto.dart';
import 'tina_dart/BaseAPI.dart';

/// VIVO OCR 服务
class OCR {
  final String appId;
  final String secretKey;
  final String apiUrl;
  final BaseAPI llm;
  final Dio _dio;
  
  /// 构造函数
  OCR({
    required this.appId,
    required this.secretKey,
    required this.apiUrl,
    required this.llm,
  }) : _dio = Dio(BaseOptions(
         connectTimeout: Duration(seconds: 15),  // 减少连接超时
         receiveTimeout: Duration(seconds: 15),  // 减少接收超时
         sendTimeout: Duration(seconds: 15),     // 添加发送超时
         contentType: 'application/x-www-form-urlencoded',
       ));
  
  /// 生成随机字符串
  String _generateNonce() {
    const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    final random = Random();
    return List.generate(8, (index) => chars[random.nextInt(chars.length)]).join();
  }
  
  /// 计算签名
  String _calculateSignature(String timestamp, String nonce) {
    try {
      // 根据Python代码的签名算法
      final uri = Uri.parse(apiUrl);
      final uriPath = uri.path;
      print('OCR签名: URI路径: $uriPath');
      
      // 构建签名字符串 - 完全按照Python代码的格式
      String canonicalQueryString = '';
      String signedHeadersString = 'x-ai-gateway-app-id:$appId\n'
          'x-ai-gateway-timestamp:$timestamp\n'
          'x-ai-gateway-nonce:$nonce';
      
      String signingString = 'POST\n$uriPath\n$canonicalQueryString\n$appId\n$timestamp\n$signedHeadersString';
      
      print('OCR签名: 签名字符串:');
      print('$signingString');
      
      // 使用HMAC-SHA256计算签名
      List<int> key = utf8.encode(secretKey);
      List<int> message = utf8.encode(signingString);
      Hmac hmac = Hmac(sha256, key);
      Digest digest = hmac.convert(message);
      
      // 返回Base64编码的签名
      final signature = base64.encode(digest.bytes);
      print('OCR签名: 计算结果: $signature');
      return signature;
    } catch (e) {
      print('OCR签名计算失败: $e');
      rethrow;
    }
  }
  
  /// 测试网络连接
  Future<bool> testConnection() async {
    try {
      print('OCR: 测试网络连接到: $apiUrl');
      final response = await _dio.get(
        'https://www.baidu.com',  // 先测试一个简单的连接
        options: Options(
          validateStatus: (status) => true,
        ),
      );
      print('OCR: 网络连接测试结果: ${response.statusCode}');
      return response.statusCode == 200;
    } catch (e) {
      print('OCR: 网络连接测试失败: $e');
      return false;
    }
  }
  
  /// 执行OCR识别
  Future<Map<String, dynamic>?> recognize(String imagePath) async {
    try {
      print('OCR: 开始处理图片: $imagePath');
      
      // 先测试网络连接
      print('OCR: 测试网络连接...');
      final connectionOk = await testConnection();
      if (!connectionOk) {
        return {
          'error_code': -1,
          'error_msg': '网络连接失败，请检查网络设置'
        };
      }
      print('OCR: 网络连接正常');
      
      // 将图像转换为Base64
      final File file = File(imagePath);
      if (!await file.exists()) {
        print('OCR: 图片文件不存在: $imagePath');
        return {'error_code': -1, 'error_msg': '图片文件不存在'};
      }
      
      final List<int> imageBytes = await file.readAsBytes();
      final String imageBase64 = base64.encode(imageBytes);
      print('OCR: 图片转换为Base64成功，大小: ${imageBase64.length}');
      
      // 生成时间戳和随机字符串
      final timestamp = (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();
      final nonce = _generateNonce();
      print('OCR: 时间戳: $timestamp, 随机数: $nonce');
      
      // 计算签名
      final signature = _calculateSignature(timestamp, nonce);
      print('OCR: 签名计算完成: $signature');
      
      // 构建请求头 - 按照Python代码的格式
      final headers = {
        'X-AI-GATEWAY-APP-ID': appId,
        'X-AI-GATEWAY-TIMESTAMP': timestamp,
        'X-AI-GATEWAY-NONCE': nonce,
        'X-AI-GATEWAY-SIGNED-HEADERS': 'x-ai-gateway-app-id;x-ai-gateway-timestamp;x-ai-gateway-nonce',
        'X-AI-GATEWAY-SIGNATURE': signature,
      };
      print('OCR: 请求头构建完成: $headers');
      
      // 构建请求数据 - 按照Python代码的格式
      final formData = {
        'image': imageBase64,
        'pos': '0',
        'businessid': 'aigc' + appId  // 与Python代码一致：'aigc' + APP_ID
      };
      print('OCR: 请求数据构建完成，businessid: aigc$appId');
      
      print('OCR: 发送请求到: $apiUrl');
      
      // 发送请求
      try {
        final response = await _dio.post(
          apiUrl,
          data: formData,
          options: Options(
            headers: headers,
            validateStatus: (status) => true, // 允许所有状态码，便于调试
          ),
        );
        
        print('OCR: 收到响应，状态码: ${response.statusCode}');
        print('OCR: 响应数据: ${response.data}');
        
        if (response.statusCode == 200) {
          return response.data;
        } else {
          print('OCR请求失败: ${response.statusCode}, ${response.data}');
          return {
            'error_code': response.statusCode,
            'error_msg': 'HTTP ${response.statusCode}: ${response.data}'
          };
        }
      } on DioException catch (dioError) {
        print('OCR网络请求异常:');
        print('  错误类型: ${dioError.type}');
        print('  错误消息: ${dioError.message}');
        
        String errorMessage;
        switch (dioError.type) {
          case DioExceptionType.connectionTimeout:
            errorMessage = '连接超时，请检查网络连接';
            break;
          case DioExceptionType.sendTimeout:
            errorMessage = '发送超时，请检查网络连接';
            break;
          case DioExceptionType.receiveTimeout:
            errorMessage = '接收超时，服务器响应缓慢';
            break;
          case DioExceptionType.badResponse:
            errorMessage = '服务器响应错误: ${dioError.response?.statusCode}';
            break;
          case DioExceptionType.cancel:
            errorMessage = '请求被取消';
            break;
          case DioExceptionType.connectionError:
            errorMessage = '网络连接错误，请检查网络设置';
            break;
          default:
            errorMessage = '网络请求失败: ${dioError.message}';
        }
        
        return {
          'error_code': dioError.response?.statusCode ?? -1,
          'error_msg': errorMessage
        };
      }
    } catch (e) {
      print('OCR识别异常: $e');
      return {
        'error_code': -1,
        'error_msg': 'OCR识别失败: $e'
      };
    }
  }
  
  /// 提取OCR结果中的文本
  String _extractTextFromResult(Map<String, dynamic> ocrResult) {
    try {
      // 检查OCR识别是否成功
      if (ocrResult.containsKey('error_code') && ocrResult['error_code'] != 0) {
        return '图像识别失败: ${ocrResult['error_msg']}';
      }
      
      String wholeText = '';
      if (ocrResult.containsKey('result') && 
          ocrResult['result'] != null) {
        
        // 处理VIVO OCR格式
        if (ocrResult['result'].containsKey('words')) {
          for (var word in ocrResult['result']['words']) {
            if (word.containsKey('words')) {
              wholeText += word['words'];
            }
          }
        }
        // 处理其他可能的格式
        else if (ocrResult['result'].containsKey('text')) {
          wholeText = ocrResult['result']['text'];
        }
      }
      
      return wholeText;
    } catch (e) {
      print('提取OCR文本失败: $e');
      return '';
    }
  }
  
  /// 将OCR结果转换为文本并使用LLM优化
  Future<Map<String, dynamic>> processToText(String imagePath) async {
    try {
      print('OCR处理: 开始处理图片 $imagePath');
      
      // 使用真实的OCR调用
      print('OCR处理: 使用真实OCR API调用');
      final ocrResult = await recognize(imagePath);
      
      // 如果需要测试，可以使用测试版本
      // final ocrResult = await recognizeTest(imagePath);
      
      if (ocrResult == null) {
        return {
          'success': false,
          'message': 'OCR识别失败，返回结果为空',
          'text': '',
        };
      }
      
      // 检查是否有错误
      if (ocrResult.containsKey('error_code') && ocrResult['error_code'] != 0) {
        final errorMsg = ocrResult['error_msg'] ?? '未知错误';
        print('OCR处理: API返回错误 - ${ocrResult['error_code']}: $errorMsg');
        return {
          'success': false,
          'message': 'OCR API错误: $errorMsg',
          'text': '',
        };
      }
      
      // 提取识别到的文本
      String wholeText = _extractTextFromResult(ocrResult);
      print('OCR处理: 提取到的原始文本长度: ${wholeText.length}');
      print('OCR处理: 原始文本内容: $wholeText');
      
      if (wholeText.isEmpty) {
        return {
          'success': false,
          'message': '未能从图片中提取到文本内容',
          'text': '',
        };
      }
      
      // 如果文本太长，截断以避免LLM API问题
      if (wholeText.length > 2000) {
        print('OCR处理: 文本过长(${wholeText.length}字符)，截断到2000字符');
        wholeText = wholeText.substring(0, 2000) + '...';
      }
      
      // 临时跳过LLM优化，直接返回OCR文本
      print('OCR处理: 暂时跳过LLM优化，直接返回OCR文本');
      return {
        'success': true,
        'message': 'OCR识别成功（跳过LLM优化）',
        'raw_text': wholeText,
        'text': wholeText,
      };
      
      /* 暂时注释掉LLM优化部分
      print('OCR处理: 开始使用LLM优化文本');
      
      try {
        // 使用LLM优化文本
        final llmResult = await llm.predict(
          input_text: wholeText,
          sys_prompt: '请你担任一位处理OCR文本的助理，因为一些截图不可避免将一些无关信息包括进来，为了正确地保留有效的信息，请你对我们输入的OCR文本进行分析，确认哪些是主要内容并保留，最终输出，只需要输出，其他的语句不需要',
        );
        
        print('OCR处理: LLM优化完成');
        
        return {
          'success': true,
          'message': 'OCR识别成功',
          'raw_text': wholeText,
          'text': llmResult['content'] ?? wholeText, // 如果LLM返回空内容，使用原始文本
        };
      } catch (llmError) {
        print('OCR处理: LLM优化失败: $llmError');
        // LLM失败时，直接返回原始OCR文本
        return {
          'success': true,
          'message': 'OCR识别成功，但LLM优化失败，返回原始文本',
          'raw_text': wholeText,
          'text': wholeText,
          'llm_error': llmError.toString(),
        };
      }
      */
      
    } catch (e) {
      print('OCR处理失败: $e');
      return {
        'success': false,
        'message': '处理文本失败: $e',
        'text': '',
      };
    }
  }
  
  /// 保存OCR识别结果到文件
  Future<Map<String, dynamic>> saveToFile(String imagePath, {String? outputPath}) async {
    try {
      // 处理OCR文本
      final processResult = await processToText(imagePath);
      
      if (!processResult['success']) {
        return processResult;
      }
      
      // 设置输出路径
      String txtPath = outputPath ?? '${path.withoutExtension(imagePath)}.txt';
      
      // 保存处理后的文本到文件
      File outputFile = File(txtPath);
      await outputFile.writeAsString(processResult['text']);
      
      return {
        'success': true,
        'message': '文本已保存到 $txtPath',
        'path': txtPath,
        'text': processResult['text'],
      };
    } catch (e) {
      print('保存OCR结果失败: $e');
      return {
        'success': false,
        'message': '保存OCR结果失败: $e',
        'text': '',
      };
    }
  }
  
  /// 简化的OCR测试方法（用于调试）
  Future<Map<String, dynamic>?> recognizeTest(String imagePath) async {
    try {
      print('OCR测试: 模拟处理图片: $imagePath');
      
      // 模拟延迟
      await Future.delayed(Duration(seconds: 2));
      
      // 返回模拟的OCR结果
      return {
        'result': {
          'words': [
            {'words': '这是一个测试图片'},
            {'words': '包含一些示例文本'},
            {'words': '用于验证OCR流程'}
          ]
        }
      };
    } catch (e) {
      print('OCR测试失败: $e');
      return {
        'error_code': -1,
        'error_msg': 'OCR测试失败: $e'
      };
    }
  }

  /// 将OCR结果转换为文本并使用LLM优化（测试版本）
} 